// site.isscloud.project.service.impl.PjLocationTemperatureServiceImpl
package site.isscloud.project.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;

import site.isscloud.project.domain.PjLocation;
import site.isscloud.project.domain.PjLocationMarker;
import site.isscloud.project.domain.PjStatsLocationTemperatureMinute;
import site.isscloud.project.domain.PjStatsTemperatureMinute;
import site.isscloud.project.mapper.PjLocationMapper;
import site.isscloud.project.mapper.PjLocationMarkerMapper;
import site.isscloud.project.mapper.PjStatsLocationTemperatureMinuteMapper;
import site.isscloud.project.mapper.PjStatsTemperatureMinuteMapper;
import site.isscloud.project.service.IPjStatsLocationTemperatureMinuteService;

/**
 * 空间位置温度统计Service业务层处理
 */
@Service
public class PjStatsLocationTemperatureMinuteServiceImpl implements IPjStatsLocationTemperatureMinuteService {

    private static final Logger log = LoggerFactory.getLogger(PjStatsLocationTemperatureMinuteServiceImpl.class);
    // 专门用于统计日志的Logger
    private static final Logger statisticLog = LoggerFactory.getLogger("statistic");

    @Autowired
    private PjLocationMapper pjLocationMapper;

    @Autowired
    private PjLocationMarkerMapper pjLocationMarkerMapper;

    @Autowired
    private PjStatsTemperatureMinuteMapper pjStatsTemperatureMinuteMapper;

    @Autowired
    private PjStatsLocationTemperatureMinuteMapper pjStatsLocationTemperatureMinuteMapper;

    /**
     * 获取最新统计时间的所有位置温度数据
     */
    @Override
    public List<PjStatsLocationTemperatureMinute> getAllLatestLocationTemperatureStats() {
        try {
            return pjStatsLocationTemperatureMinuteMapper.selectAllLatestTemperatureStats();
        } catch (Exception e) {
            log.error("获取所有最新位置温度数据失败", e);
            return new ArrayList<>();
        }
    }

    /**
     * 获取指定设备通道的最新位置温度数据
     */
    @Override
    public List<PjStatsLocationTemperatureMinute> getLatestLocationTemperatureStatsByDeviceChannel(String deviceNo, Integer channelNo) {
        try {
            if (deviceNo == null || deviceNo.trim().isEmpty() || channelNo == null) {
                log.warn("设备编号或通道号为空，deviceNo: {}, channelNo: {}", deviceNo, channelNo);
                return new ArrayList<>();
            }
            return pjStatsLocationTemperatureMinuteMapper.selectLatestTemperatureStatsByDeviceChannel(deviceNo, channelNo);
        } catch (Exception e) {
            log.error("获取设备{}通道{}最新位置温度数据失败", deviceNo, channelNo, e);
            return new ArrayList<>();
        }
    }

    /**
     * 批量获取多个设备通道的最新位置温度数据
     */
    @Override
    public List<PjStatsLocationTemperatureMinute> getLatestLocationTemperatureStatsByDeviceChannels(List<Map<String, Object>> deviceChannelMaps) {
        try {
            if (deviceChannelMaps == null || deviceChannelMaps.isEmpty()) {
                log.info("设备通道列表为空，返回空结果");
                return new ArrayList<>();
            }

            // 验证参数格式
            for (Map<String, Object> dcMap : deviceChannelMaps) {
                if (!dcMap.containsKey("deviceNo") || !dcMap.containsKey("channelNo")) {
                    log.warn("设备通道Map缺少必要字段: {}", dcMap);
                    return new ArrayList<>();
                }
            }

            return pjStatsLocationTemperatureMinuteMapper.selectLatestTemperatureStatsByDeviceChannels(deviceChannelMaps);
        } catch (Exception e) {
            log.error("批量获取设备通道最新位置温度数据失败，设备通道数: {}",
                    deviceChannelMaps != null ? deviceChannelMaps.size() : 0, e);
            return new ArrayList<>();
        }
    }

    /**
     * 生成空间位置温度统计数据（无参版本，自动计算上一分钟）
     */
    @Override
    public void generateLocationTemperatureMinuteStats() {
        // 计算上一分钟的时间
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.MINUTE, -1);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        Date statTime = calendar.getTime();

        statisticLog.info("自动计算统计时间: {}", statTime);
        statisticLog.debug("统计时间详情: 年={}, 月={}, 日={}, 时={}, 分={}",
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH) + 1,
                calendar.get(Calendar.DAY_OF_MONTH),
                calendar.get(Calendar.HOUR_OF_DAY),
                calendar.get(Calendar.MINUTE));

        // 调用原有的统计方法
        generateLocationTemperatureMinuteStats(statTime);
    }

    /**
     * 生成空间位置温度统计数据（无事务，逐级提交版本）
     */
    @Override
    public void generateLocationTemperatureMinuteStats(Date statTime) {
        statisticLog.info("=== 开始生成空间位置温度分钟统计数据 ===");
        statisticLog.info("统计时间: {}", statTime);
        long startTime = System.currentTimeMillis();

        int totalSuccessCount = 0;
        int totalFailCount = 0;

        try {
            // 1. 获取所有活跃的空间标记
            statisticLog.info("步骤1: 获取活跃的空间标记");
            List<PjLocationMarker> allMarkers = pjLocationMarkerMapper.selectAllActive();
            statisticLog.info("获取到 {} 个活跃的空间标记", allMarkers.size());

            // 2. 获取上一分钟的统计数据
            statisticLog.info("步骤2: 获取温度统计数据");
            List<PjStatsTemperatureMinute> temperatureStats = pjStatsTemperatureMinuteMapper.selectByStatTime(statTime);
            statisticLog.info("获取到 {} 条温度统计数据", temperatureStats.size());

            if (temperatureStats.isEmpty()) {
                statisticLog.warn("未找到指定时间的温度统计数据: {}", statTime);
                return;
            }

            // 3. 按设备编号和通道号分组温度数据
            Map<String, PjStatsTemperatureMinute> temperatureMap = temperatureStats.stream()
                    .collect(Collectors.toMap(
                            stat -> stat.getDeviceNo() + "_" + stat.getChannelNo(),
                            stat -> stat
                    ));

            // 4. 构建空间树结构 - 从PjLocation表构建
            statisticLog.info("步骤3: 构建空间树结构");
            Map<String, LocationNode> locationTree = buildLocationTree(allMarkers);
            statisticLog.info("构建空间树完成，共 {} 个节点", locationTree.size());

            // 5. 处理叶子节点（最细粒度的空间）- 立即提交
            statisticLog.info("步骤4: 处理叶子节点");
            LeafProcessResult leafResult = processLeafNodesWithStats(locationTree, temperatureMap, statTime);
            statisticLog.info("叶子节点处理完成，共插入 {} 条数据，失败 {} 条", leafResult.successCount, leafResult.failCount);
            totalSuccessCount += leafResult.successCount;
            totalFailCount += leafResult.failCount;

            // 6. 按层级处理父节点 - 逐级提交
            statisticLog.info("步骤5: 处理父节点");
            ParentProcessResult parentResult = processParentNodesByLevelWithStats(locationTree, statTime);
            statisticLog.info("父节点处理完成，共插入 {} 条数据，失败 {} 条", parentResult.successCount, parentResult.failCount);
            totalSuccessCount += parentResult.successCount;
            totalFailCount += parentResult.failCount;

            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;

            statisticLog.info("=== 空间位置温度统计完成 ===");
            statisticLog.info("统计汇总:");
            statisticLog.info("- 总处理节点: {} 个", totalSuccessCount + totalFailCount);
            statisticLog.info("- 成功处理: {} 个节点", totalSuccessCount);
            statisticLog.info("- 处理失败: {} 个节点", totalFailCount);
            statisticLog.info("- 成功率: {}%", (totalSuccessCount + totalFailCount) > 0 ?
                    String.format("%.2f", (totalSuccessCount * 100.0 / (totalSuccessCount + totalFailCount))) : "0.00");
            statisticLog.info("- 总耗时: {} 毫秒", duration);
            statisticLog.info("统计时间: {}", statTime);

        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            long duration = endTime - startTime;

            statisticLog.error("=== 空间位置温度统计失败 ===");
            statisticLog.error("错误信息: {}", e.getMessage());
            statisticLog.error("统计时间: {}", statTime);
            statisticLog.error("已成功处理: {} 个节点", totalSuccessCount);
            statisticLog.error("处理失败: {} 个节点", totalFailCount);
            statisticLog.error("总耗时: {} 毫秒", duration);
            statisticLog.error("异常堆栈:", e);

            log.error("生成空间位置温度统计数据失败", e);
            throw new RuntimeException("生成空间位置温度统计数据失败", e);
        }
    }

    /**
     * 处理叶子节点 - 带统计信息
     */
    private LeafProcessResult processLeafNodesWithStats(
            Map<String, LocationNode> locationTree,
            Map<String, PjStatsTemperatureMinute> temperatureMap,
            Date statTime) {

        statisticLog.info("开始处理叶子节点，总节点数: {}", locationTree.size());
        List<PjStatsLocationTemperatureMinute> leafStats = new ArrayList<>();
        int processedCount = 0;
        int errorCount = 0;
        int skippedCount = 0;

        for (LocationNode node : locationTree.values()) {
            if (node.getChildren().isEmpty()) { // 叶子节点
                PjLocationMarker marker = node.getMarker();
                if (marker == null) {
                    skippedCount++;
                    continue; // 跳过没有marker的叶子节点
                }

                try {
                    String key = marker.getDeviceNo() + "_" + marker.getChannelNo();
                    PjStatsTemperatureMinute tempStat = temperatureMap.get(key);

                    if (tempStat != null) {
                        PjStatsLocationTemperatureMinute locationStat = calculateLocationStats(marker, tempStat, statTime);
                        if (locationStat != null) {
                            // 立即插入数据库
                            pjStatsLocationTemperatureMinuteMapper.insertPjStatsLocationTemperatureMinute(locationStat);
                            leafStats.add(locationStat);
                            node.setStats(locationStat);
                            processedCount++;

                            statisticLog.debug("叶子节点插入成功 - 空间编码: {}, 设备: {}, 通道: {}",
                                    marker.getLcCode(), marker.getDeviceNo(), marker.getChannelNo());
                        } else {
                            errorCount++;
                            statisticLog.warn("叶子节点统计计算返回空 - 空间编码: {}, 设备: {}, 通道: {}",
                                    marker.getLcCode(), marker.getDeviceNo(), marker.getChannelNo());
                        }
                    } else {
                        errorCount++;
                        statisticLog.warn("未找到温度统计数据 - 空间编码: {}, 设备: {}, 通道: {}, 查询键: {}",
                                marker.getLcCode(), marker.getDeviceNo(), marker.getChannelNo(), key);
                    }
                } catch (Exception e) {
                    errorCount++;
                    statisticLog.error("处理叶子节点失败 - 空间编码: {}, 设备: {}, 通道: {}, 错误: {}",
                            marker.getLcCode(), marker.getDeviceNo(), marker.getChannelNo(),
                            e.getMessage());
                }
            }
        }

        statisticLog.info("叶子节点处理完成: 总叶子节点={}, 成功={}, 失败={}, 跳过(无标记)={}",
                processedCount + errorCount + skippedCount, processedCount, errorCount, skippedCount);

        return new LeafProcessResult(processedCount, errorCount, leafStats);
    }

    /**
     * 按层级处理父节点 - 带统计信息
     */
    private ParentProcessResult processParentNodesByLevelWithStats(Map<String, LocationNode> locationTree, Date statTime) {
        statisticLog.info("开始处理父节点，总节点数: {}", locationTree.size());

        // 按层级深度分组
        Map<Integer, List<LocationNode>> nodesByLevel = groupNodesByLevel(locationTree);

        // 从最深层开始向上处理（叶子节点已经在第0层处理过了）
        int maxLevel = nodesByLevel.keySet().stream().max(Integer::compareTo).orElse(0);
        int totalProcessed = 0;
        int totalErrors = 0;

        for (int level = maxLevel; level >= 0; level--) {
            List<LocationNode> levelNodes = nodesByLevel.get(level);
            if (levelNodes == null) continue;

            statisticLog.info("开始处理第 {} 层节点，共 {} 个节点", level, levelNodes.size());

            int levelProcessed = 0;
            int levelErrors = 0;

            for (LocationNode node : levelNodes) {
                // 只处理非叶子节点（叶子节点已经在前面处理过了）
                if (!node.getChildren().isEmpty()) {
                    try {
                        PjStatsLocationTemperatureMinute parentStat = aggregateParentStats(node, statTime);
                        if (parentStat != null) {
                            // 立即插入数据库
                            pjStatsLocationTemperatureMinuteMapper.insertPjStatsLocationTemperatureMinute(parentStat);
                            node.setStats(parentStat);
                            levelProcessed++;

                            statisticLog.debug("父节点插入成功 - 层级: {}, 空间编码: {}", level, node.getLocation().getLcCode());
                        } else {
                            levelErrors++;
                            statisticLog.warn("父节点统计计算返回空 - 层级: {}, 空间编码: {}",
                                    level, node.getLocation().getLcCode());
                        }
                    } catch (Exception e) {
                        levelErrors++;
                        statisticLog.error("处理父节点失败 - 层级: {}, 空间编码: {}, 错误: {}",
                                level, node.getLocation().getLcCode(), e.getMessage());
                    }
                }
            }

            totalProcessed += levelProcessed;
            totalErrors += levelErrors;

            statisticLog.info("第 {} 层节点处理完成: 成功={}, 失败={}", level, levelProcessed, levelErrors);
        }

        statisticLog.info("父节点处理完成: 总成功={}, 总失败={}", totalProcessed, totalErrors);
        return new ParentProcessResult(totalProcessed, totalErrors);
    }

    /**
     * 构建空间位置树 - 从PjLocation表构建完整树结构，再与PjLocationMarker关联
     */
    private Map<String, LocationNode> buildLocationTree(List<PjLocationMarker> markers) {
        Map<String, LocationNode> nodeMap = new HashMap<>();

        try {
            // 1. 从PjLocation表获取所有空间位置数据
            statisticLog.info("获取所有活跃的空间位置数据");
            List<PjLocation> allLocations = pjLocationMapper.selectAllActive();
            statisticLog.info("获取到 {} 个活跃的空间位置", allLocations.size());

            // 2. 构建完整的空间位置树
            statisticLog.info("构建完整的空间位置树");
            Map<String, LocationNode> locationTree = buildCompleteLocationTree(allLocations);

            // 3. 将PjLocationMarker数据关联到对应的树节点
            statisticLog.info("关联空间标记数据到树节点");
            associateMarkersWithTree(locationTree, markers);

            // 4. 过滤掉没有对应PjLocationMarker的节点（只保留有标记数据的节点）
            statisticLog.info("过滤无标记数据的节点");
            nodeMap = filterNodesWithMarkers(locationTree);

            statisticLog.info("空间位置树构建完成，共 {} 个有效节点", nodeMap.size());

        } catch (Exception e) {
            statisticLog.error("构建空间位置树失败，错误: {}", e.getMessage());
            log.error("构建空间位置树失败", e);
            throw new RuntimeException("构建空间位置树失败", e);
        }

        return nodeMap;
    }

    /**
     * 从PjLocation数据构建完整的空间位置树
     */
    private Map<String, LocationNode> buildCompleteLocationTree(List<PjLocation> locations) {
        statisticLog.debug("开始构建完整空间树，位置数量: {}", locations.size());
        Map<String, LocationNode> nodeMap = new HashMap<>();

        // 首先创建所有节点
        for (PjLocation location : locations) {
            LocationNode node = new LocationNode();
            node.setLocation(location);
            node.setMarker(null); // 初始化为null
            node.setChildren(new ArrayList<>());
            nodeMap.put(location.getLcCode(), node);
        }

        // 构建父子关系
        int relationshipCount = 0;
        for (LocationNode node : nodeMap.values()) {
            String parentCode = getParentLocationCode(node.getLocation().getLcCode());
            if (parentCode != null && nodeMap.containsKey(parentCode)) {
                nodeMap.get(parentCode).getChildren().add(node);
                relationshipCount++;
            }
        }

        statisticLog.debug("空间树构建完成: 节点数={}, 父子关系数={}", nodeMap.size(), relationshipCount);
        return nodeMap;
    }

    /**
     * 将PjLocationMarker数据关联到树节点
     */
    private void associateMarkersWithTree(Map<String, LocationNode> locationTree, List<PjLocationMarker> markers) {
        statisticLog.debug("开始关联标记数据，标记数量: {}", markers.size());

        // 创建lcCode到marker的映射
        Map<String, PjLocationMarker> markerMap = markers.stream()
                .collect(Collectors.toMap(PjLocationMarker::getLcCode, marker -> marker));

        // 将marker关联到对应的树节点
        int associatedCount = 0;
        for (LocationNode node : locationTree.values()) {
            String lcCode = node.getLocation().getLcCode();
            if (markerMap.containsKey(lcCode)) {
                node.setMarker(markerMap.get(lcCode));
                associatedCount++;
            }
        }

        statisticLog.debug("标记数据关联完成: 总节点数={}, 成功关联={}", locationTree.size(), associatedCount);
    }

    /**
     * 计算空间统计数据 - 优化版本，直接使用Map
     */
    private PjStatsLocationTemperatureMinute calculateLocationStats(
            PjLocationMarker marker,
            PjStatsTemperatureMinute tempStat,
            Date statTime) {

        try {
            // 直接使用已经解析好的Map数据
            Map<Integer, BigDecimal> maxTempsMap = tempStat.getMaxTemperaturesMap();
            Map<Integer, BigDecimal> minTempsMap = tempStat.getMinTemperaturesMap();
            Map<Integer, BigDecimal> avgTempsMap = tempStat.getAvgTemperaturesMap();

            if (maxTempsMap == null || maxTempsMap.isEmpty()) {
                statisticLog.warn("温度数据Map为空 - 空间编码: {}, 设备: {}, 通道: {}",
                        marker.getLcCode(), marker.getDeviceNo(), marker.getChannelNo());
                return null;
            }

            int markerStart = marker.getMarkerStart();
            int markerEnd = marker.getMarkerEnd();
            Double startMeter = tempStat.getStartMeter();
            Double endMeter = tempStat.getEndMeter();

            // 验证米标范围
            if (startMeter == null || endMeter == null) {
                statisticLog.warn("温度统计数据缺少米标范围 - 空间编码: {}, startMeter: {}, endMeter: {}",
                        marker.getLcCode(), startMeter, endMeter);
                return null;
            }

            // 计算实际的数据索引范围
            int dataStartIndex = markerStart - startMeter.intValue() + 1;
            int dataEndIndex = markerEnd - startMeter.intValue() + 1;

            statisticLog.debug("米标转换 - 空间编码: {}, 标记范围: {}-{}, 数据索引: {}-{}",
                    marker.getLcCode(), markerStart, markerEnd, dataStartIndex, dataEndIndex);

            // 提取对应区间的温度数据
            List<BigDecimal> maxValues = new ArrayList<>();
            List<BigDecimal> minValues = new ArrayList<>();
            List<BigDecimal> avgValues = new ArrayList<>();

            JSONObject tempData = new JSONObject();
            JSONArray maxDataArray = new JSONArray();
            JSONArray minDataArray = new JSONArray();
            JSONArray avgDataArray = new JSONArray();

            int validDataCount = 0;
            for (int i = dataStartIndex; i <= dataEndIndex; i++) {
                BigDecimal maxTemp = maxTempsMap.get(i);
                BigDecimal minTemp = minTempsMap.get(i);
                BigDecimal avgTemp = avgTempsMap != null ? avgTempsMap.get(i) : null;

                // 如果高温数据存在，则认为该位置有效
                if (maxTemp != null) {
                    maxValues.add(maxTemp);
                    minValues.add(minTemp != null ? minTemp : BigDecimal.ZERO);
                    avgValues.add(avgTemp != null ? avgTemp : BigDecimal.ZERO);

                    // 构建详细数据
                    JSONObject maxObj = new JSONObject();
                    maxObj.put(String.valueOf(markerStart + (i - dataStartIndex)), maxTemp);
                    maxDataArray.add(maxObj);

                    JSONObject minObj = new JSONObject();
                    minObj.put(String.valueOf(markerStart + (i - dataStartIndex)),
                            minTemp != null ? minTemp : BigDecimal.ZERO);
                    minDataArray.add(minObj);

                    JSONObject avgObj = new JSONObject();
                    avgObj.put(String.valueOf(markerStart + (i - dataStartIndex)),
                            avgTemp != null ? avgTemp : BigDecimal.ZERO);
                    avgDataArray.add(avgObj);

                    validDataCount++;
                }
            }

            if (validDataCount == 0) {
                statisticLog.warn("温度数据区间无有效数据 - 空间编码: {}, 索引范围: {}-{}, Map大小: {}",
                        marker.getLcCode(), dataStartIndex, dataEndIndex, maxTempsMap.size());
                return null;
            }

            statisticLog.debug("提取到 {} 个有效数据点 - 空间编码: {}", validDataCount, marker.getLcCode());

            // 计算统计值
            BigDecimal maxTemperature = maxValues.stream()
                    .max(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO);

            BigDecimal minTemperature = minValues.stream()
                    .filter(val -> val.compareTo(BigDecimal.ZERO) != 0) // 过滤掉零值
                    .min(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO);

            BigDecimal avgTemperature = avgValues.stream()
                    .filter(val -> val.compareTo(BigDecimal.ZERO) != 0) // 过滤掉零值
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
                    .divide(BigDecimal.valueOf(avgValues.stream()
                                    .filter(val -> val.compareTo(BigDecimal.ZERO) != 0).count()),
                            2, RoundingMode.HALF_UP);

            // 如果平均值计算失败（如除零），使用高温和低温的平均值
            if (avgTemperature.compareTo(BigDecimal.ZERO) == 0 &&
                    maxTemperature.compareTo(BigDecimal.ZERO) > 0 &&
                    minTemperature.compareTo(BigDecimal.ZERO) > 0) {
                avgTemperature = maxTemperature.add(minTemperature)
                        .divide(new BigDecimal("2"), 2, RoundingMode.HALF_UP);
            }

            // 构建详细温度数据JSON
            tempData.put("max_temperatures", maxDataArray);
            tempData.put("min_temperatures", minDataArray);
            tempData.put("avg_temperatures", avgDataArray);

            // 创建统计记录
            PjStatsLocationTemperatureMinute locationStat = new PjStatsLocationTemperatureMinute();
            locationStat.setLcCode(marker.getLcCode());
            locationStat.setDeviceNo(marker.getDeviceNo());
            locationStat.setChannelNo(marker.getChannelNo());
            locationStat.setStatTime(statTime);
            locationStat.setMaxTemperature(maxTemperature);
            locationStat.setMinTemperature(minTemperature);
            locationStat.setAvgTemperature(avgTemperature);
            locationStat.setMarkerCount(marker.getMarkerLength());
            locationStat.setSampleCount(validDataCount); // 使用实际有效数据点数
            locationStat.setTemperatureData(tempData.toJSONString());

            statisticLog.debug("计算空间统计完成 - 空间编码: {}, 最大温度: {}, 最小温度: {}, 平均温度: {}",
                    marker.getLcCode(), maxTemperature, minTemperature, avgTemperature);

            return locationStat;

        } catch (Exception e) {
            statisticLog.error("计算空间统计数据失败 - 空间编码: {}, 错误: {}", marker.getLcCode(), e.getMessage());
            statisticLog.error("异常堆栈:", e);
            return null;
        }
    }

    /**
     * 汇总父节点统计数据
     */
    private PjStatsLocationTemperatureMinute aggregateParentStats(LocationNode parentNode, Date statTime) {
        try {
            List<PjStatsLocationTemperatureMinute> childStats = parentNode.getChildren().stream()
                    .map(LocationNode::getStats)
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

            if (childStats.isEmpty()) {
                statisticLog.warn("父节点没有有效的子节点统计数据 - 空间编码: {}", parentNode.getLocation().getLcCode());
                return null;
            }

            // 计算汇总值
            BigDecimal maxTemperature = childStats.stream()
                    .map(PjStatsLocationTemperatureMinute::getMaxTemperature)
                    .max(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO);

            BigDecimal minTemperature = childStats.stream()
                    .map(PjStatsLocationTemperatureMinute::getMinTemperature)
                    .min(BigDecimal::compareTo)
                    .orElse(BigDecimal.ZERO);

            BigDecimal avgTemperature = childStats.stream()
                    .map(PjStatsLocationTemperatureMinute::getAvgTemperature)
                    .reduce(BigDecimal.ZERO, BigDecimal::add)
                    .divide(BigDecimal.valueOf(childStats.size()), 2, RoundingMode.HALF_UP);

            // 构建详细数据
            JSONObject tempData = new JSONObject();
            JSONArray maxDataArray = new JSONArray();
            JSONArray minDataArray = new JSONArray();
            JSONArray avgDataArray = new JSONArray();

            for (PjStatsLocationTemperatureMinute childStat : childStats) {
                JSONObject maxObj = new JSONObject();
                maxObj.put(childStat.getLcCode(), childStat.getMaxTemperature());
                maxDataArray.add(maxObj);

                JSONObject minObj = new JSONObject();
                minObj.put(childStat.getLcCode(), childStat.getMinTemperature());
                minDataArray.add(minObj);

                JSONObject avgObj = new JSONObject();
                avgObj.put(childStat.getLcCode(), childStat.getAvgTemperature());
                avgDataArray.add(avgObj);
            }

            tempData.put("max_temperatures", maxDataArray);
            tempData.put("min_temperatures", minDataArray);
            tempData.put("avg_temperatures", avgDataArray);

            // 创建父节点统计记录 - 从PjLocationMarker获取deviceNo和channelNo
            PjStatsLocationTemperatureMinute parentStat = new PjStatsLocationTemperatureMinute();
            parentStat.setLcCode(parentNode.getLocation().getLcCode());
            // 修改这里：从PjLocationMarker获取设备编号和通道号
            if (parentNode.getMarker() != null) {
                parentStat.setDeviceNo(parentNode.getMarker().getDeviceNo());
                parentStat.setChannelNo(parentNode.getMarker().getChannelNo());
            } else {
                // 如果父节点没有直接的marker，可以从子节点中获取（通常父节点不会有直接的marker）
                PjStatsLocationTemperatureMinute firstChild = childStats.get(0);
                parentStat.setDeviceNo(firstChild.getDeviceNo());
                parentStat.setChannelNo(firstChild.getChannelNo());
            }
            parentStat.setStatTime(statTime);
            parentStat.setMaxTemperature(maxTemperature);
            parentStat.setMinTemperature(minTemperature);
            parentStat.setAvgTemperature(avgTemperature);
            parentStat.setMarkerCount(childStats.stream().mapToInt(PjStatsLocationTemperatureMinute::getMarkerCount).sum());
            parentStat.setSampleCount(childStats.stream().mapToInt(PjStatsLocationTemperatureMinute::getSampleCount).sum());
            parentStat.setTemperatureData(tempData.toJSONString());

            statisticLog.debug("父节点统计汇总完成 - 空间编码: {}, 子节点数: {}", parentNode.getLocation().getLcCode(), childStats.size());

            return parentStat;

        } catch (Exception e) {
            statisticLog.error("汇总父节点统计数据失败 - 空间编码: {}, 错误: {}",
                    parentNode.getLocation().getLcCode(), e.getMessage());
            return null;
        }
    }

    // 辅助类用于返回统计结果
    private static class LeafProcessResult {
        int successCount;
        int failCount;
        List<PjStatsLocationTemperatureMinute> stats;

        LeafProcessResult(int successCount, int failCount, List<PjStatsLocationTemperatureMinute> stats) {
            this.successCount = successCount;
            this.failCount = failCount;
            this.stats = stats;
        }
    }

    private static class ParentProcessResult {
        int successCount;
        int failCount;

        ParentProcessResult(int successCount, int failCount) {
            this.successCount = successCount;
            this.failCount = failCount;
        }
    }

    // 以下原有方法保持不变，只添加日志
    private Map<String, LocationNode> filterNodesWithMarkers(Map<String, LocationNode> locationTree) {
        Map<String, LocationNode> filteredMap = new HashMap<>();

        // 遍历所有节点，只保留有marker的节点及其所有祖先节点
        for (LocationNode node : locationTree.values()) {
            if (hasMarkerOrDescendantHasMarker(node)) {
                filteredMap.put(node.getLocation().getLcCode(), node);
            }
        }

        // 重新构建过滤后的树的父子关系
        rebuildParentChildRelationships(filteredMap);

        return filteredMap;
    }

    private boolean hasMarkerOrDescendantHasMarker(LocationNode node) {
        if (node.getMarker() != null) {
            return true;
        }

        for (LocationNode child : node.getChildren()) {
            if (hasMarkerOrDescendantHasMarker(child)) {
                return true;
            }
        }

        return false;
    }

    private void rebuildParentChildRelationships(Map<String, LocationNode> filteredNodes) {
        // 清空所有节点的子节点列表
        for (LocationNode node : filteredNodes.values()) {
            node.setChildren(new ArrayList<>());
        }

        // 重新建立父子关系
        for (LocationNode node : filteredNodes.values()) {
            String parentCode = getParentLocationCode(node.getLocation().getLcCode());
            while (parentCode != null) {
                if (filteredNodes.containsKey(parentCode)) {
                    // 找到最近的已过滤的祖先节点
                    if (!filteredNodes.get(parentCode).getChildren().contains(node)) {
                        filteredNodes.get(parentCode).getChildren().add(node);
                    }
                    break;
                }
                // 如果父节点不在过滤后的节点中，继续向上查找
                parentCode = getParentLocationCode(parentCode);
            }
        }
    }

    private String getParentLocationCode(String lcCode) {
        if (lcCode == null || !lcCode.contains("-")) {
            return null;
        }

        String[] parts = lcCode.split("-");
        if (parts.length <= 1) {
            return null;
        }

        StringBuilder parentCode = new StringBuilder();
        for (int i = 0; i < parts.length - 1; i++) {
            if (i > 0) {
                parentCode.append("-");
            }
            parentCode.append(parts[i]);
        }

        return parentCode.toString();
    }

    private Map<Integer, List<LocationNode>> groupNodesByLevel(Map<String, LocationNode> locationTree) {
        Map<Integer, List<LocationNode>> nodesByLevel = new HashMap<>();

        for (LocationNode node : locationTree.values()) {
            int level = calculateNodeLevel(node.getLocation().getLcCode());
            nodesByLevel.computeIfAbsent(level, k -> new ArrayList<>()).add(node);
        }

        return nodesByLevel;
    }

    private int calculateNodeLevel(String lcCode) {
        if (lcCode == null) return 0;
        return (int) lcCode.chars().filter(ch -> ch == '-').count();
    }

    /**
     * 空间节点内部类
     */
    private static class LocationNode {
        private PjLocation location;
        private PjLocationMarker marker;
        private List<LocationNode> children;
        private PjStatsLocationTemperatureMinute stats;

        public PjLocation getLocation() { return location; }
        public void setLocation(PjLocation location) { this.location = location; }
        public PjLocationMarker getMarker() { return marker; }
        public void setMarker(PjLocationMarker marker) { this.marker = marker; }
        public List<LocationNode> getChildren() { return children; }
        public void setChildren(List<LocationNode> children) { this.children = children; }
        public PjStatsLocationTemperatureMinute getStats() { return stats; }
        public void setStats(PjStatsLocationTemperatureMinute stats) { this.stats = stats; }
    }
}